#encoding:utf-8
from django import forms
from django.utils.translation import ugettext_lazy as _
from countries_states.models import Country, State
from django.db.models import Q


def countries():
    """Get country selections."""
    return Country.objects.filter(active=True)

def states_for_country(country=None, translator=_):
    """
    Get state selections based on the country parameter.
    """
    choices = [('', translator(u'No aplica'))]

    if country:
        states = country.state_set.filter(active=True)
        if states.count() > 0:
            choices = [('', translator(u'Seleccione'))]
            choices.extend([(state.abbr or state.name, state.name) for state in states])

    return choices

def municipals_for_state(state=None, translator=_):
    """
    Get municipal selections based on the state parameter.
    """
    choices = [('', translator(u'No aplica'))]

    if state:
        municipals = state.municipal_set.all()
        if municipals.count() > 0:
            choices = [('', translator(u'Seleccione'))]
            choices.extend([(municipal.pk, municipal.name) for municipal in municipals])

    return choices

class CountryStateForm(forms.Form):
    """
    A basic form for Country and State/Province.
    """
    country = forms.ModelChoiceField(
        queryset=countries(),
        required=True,
        label=_(u'País'),
        empty_label=_(u'Seleccione'),
        initial=Country.objects.get(iso2_code='MX')
    )

    state = forms.ModelChoiceField(
        label=_(u'Estado'),
        empty_label=_(u'Seleccione mmmmm'),
        error_messages={'required': _(u"Seleccione un Estado/Provincia")},
        # widget=forms.Select(
        #     choices=states_for_country(country=Country.objects.get(iso2_code='MX'))
        # ),
        queryset=State.objects.none(),
        # initial=State.objects.filter(Country.objects.get(iso2_code='MX'))
    )

    municipal = forms.CharField(
        max_length=80,
        required=False,
        label=_(u'Municipio'),
        error_messages={'required': _(u"Seleccione un municipio")},
        widget=forms.Select(
            choices=municipals_for_state()
        )
    )

    def __init__(self, *args, **kwargs):
        super(CountryStateForm, self).__init__(*args, **kwargs)

        if self.is_bound:
            # if the user has already chosen the country and submitted,
            # populate the states/provinces accordingly.

            try:
                country_obj = self.fields['country'].clean(self.data.get('country'))
            except:
                country_obj = None

            try:
                state_obj = self.fields['state'].clean(self.data.get('state'))
            except:
                state_obj = None

            state_choices = states_for_country(country_obj)
            self.fields['state'] = forms.ChoiceField(label=_(u'Estado'),
                                                     choices=state_choices,
                                                     required=len(state_choices) > 1)

            municipal_choices = municipals_for_state(state_obj)
            self.fields['municipal'] = forms.ChoiceField(label=_(u'Municipio'),
                                                     choices=municipal_choices,
                                                     required=len(municipal_choices) > 1)

    def clean_country(self):
        if not self.cleaned_data.get('country'):
            raise forms.ValidationError(_(u'Seleccione un país'))
        return self.cleaned_data['country']

    def _check_state(self, data, country):
        if country and country.state_set.filter(active=True):
            if not data:
                raise forms.ValidationError(_(u'Seleccione un estado'))
            if (country.state_set
                    .filter(active=True)
                    .filter(Q(name__iexact=data) | Q(abbr__iexact=data))
                    .count() != 1):
                raise forms.ValidationError(_(u'Estado inválido'))
    
    def clean_state(self):
        data = self.cleaned_data.get('state')

        country = self.fields['country'].clean(self.data.get('country'))
        if country == None:
            raise forms.ValidationError(_(u'Seleccione un país'))
        self._check_state(data, country)

        return data

    def _check_municipal(self, data, state):
        if state:
            if not data:
                raise forms.ValidationError(_(u'Seleccione un municipio'))
            if (state.municipal_set
                    .filter(Q(name__iexact=data))
                    .count() != 1):
                raise forms.ValidationError(_(u'Municipio inválido'))

    def clean_municipal(self):
        data = self.cleaned_data.get('municipal')

        state = self.fields['state'].clean(self.data.get('state'))
        if state == None:
            raise forms.ValidationError(_(u'Seleccione un estado'))
        self._check_municipal(data, state)

        return data